package com.example.amusic.service

import android.content.ComponentName
import android.content.Context
import androidx.media3.common.MediaItem
import androidx.media3.common.Player
import androidx.media3.session.MediaController
import androidx.media3.session.SessionToken
import com.example.amusic.service.MediaConstants.DEFAULT_INDEX
import com.example.amusic.service.MediaConstants.DEFAULT_POSITION_MS
import io.appwrite.models.Session
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.guava.await
import kotlinx.coroutines.launch

class MusicServiceConnection(val context: Context) {
    private var mediaController: MediaController? = null

    private val _musicState = MutableStateFlow(MusicState())
    val musicState = _musicState.asStateFlow()

    private val coroutineScope = CoroutineScope(Dispatchers.Main + SupervisorJob())

    fun init() {
        coroutineScope.launch {
            mediaController = MediaController.Builder(
                context, SessionToken(context, ComponentName(context, MusicService::class.java))
            ).buildAsync().await().apply {
                addListener(PlayerListener())
            }
        }
    }

    fun skipPreious() = mediaController?.run {
        seekToPrevious()
        play()
    }

    fun play() = mediaController?.play()

    fun pause() = mediaController?.pause()

    fun skipNext() = mediaController?.run {
        seekToNext()
        play()
    }

    fun seekTo(position: Long) = mediaController?.run {
        seekTo(position)
        play()
    }

    fun skipToIndex(index: Int, position: Long = DEFAULT_POSITION_MS) = mediaController?.run {
        seekTo(index, position)
        play()
    }


    fun playSongs(
        songList: List<MediaItem>,
        startIndex: Int = DEFAULT_INDEX,
        startPositionMs: Long = DEFAULT_POSITION_MS
    ) {
        mediaController?.run {
            setMediaItems(songList, startIndex, startPositionMs)
            prepare()
            play()
        }
//        coroutineScope.launch { setPlayingQueueIdsUseCase(playingQueueIds = songs.map(Song::mediaId)) }
    }

    private inner class PlayerListener : Player.Listener {
        override fun onEvents(player: Player, events: Player.Events) {
            if (events.containsAny(
                    Player.EVENT_PLAYBACK_STATE_CHANGED,
                    Player.EVENT_MEDIA_METADATA_CHANGED,
                    Player.EVENT_PLAY_WHEN_READY_CHANGED
                )
            ) {
                updateMusicState(player)
            }

            if (events.contains(Player.EVENT_MEDIA_ITEM_TRANSITION)) {
                updatePlayingQueueIndex(player)
            }
        }
    }

    private fun updateMusicState(player: Player) = with(player) {
        _musicState.update {
            it.copy(
                currentMediaId = currentMediaItem?.mediaId.orEmpty(),
                playbackState = playbackState.asPlaybackState(),
                playWhenReady = playWhenReady,
                duration = duration.orDefaultTimestamp()
            )
        }
    }

    private fun updatePlayingQueueIndex(player: Player) {
        val index = player.currentMediaItemIndex
        _musicState.update {
            it.copy(currentSongIndex = index)
        }
        coroutineScope.launch {

        }
    }

}